#ifndef signature_manager_h
#define signature_manager_h

#include <string>
#include <stdexcept>
#include <iostream>
#include <utility>
#include <type_traits>
#include <utility>
#include <fstream>
#include <mutex>

#include "Hash.h"


/*
消息明文:
内容：
- 内容字节流（std::vector<uint8_t> BYTE_VECTOR）
- 哈希函数指针（Hash*）

*/
class PlainMessage {
private:
    BYTE_VECTOR bytes;
    Hash* hash_function;
    mutable std::mutex mutex_;
public:
    using BYTE_VECTOR = std::vector<uint8_t>;

    PlainMessage(Hash* hash) { hash_function = hash; }
    PlainMessage(const BYTE_VECTOR& msg, Hash* hash) : bytes(msg), hash_function(hash) {}

    ~PlainMessage();

    HASH_VALUE get_hash_data() const;
    HASH_VALUE get_hash_data_with_prefix(const BYTE_VECTOR& prefix) const;
    HASH_VALUE get_hash_data_with_suffix(const BYTE_VECTOR& suffix) const;

    BYTE_VECTOR::const_iterator get_data_begin() const;
    BYTE_VECTOR::const_iterator get_data_end() const;


    bool read_file_to_bytes(const std::string& file_path) {
        // 以二进制模式打开文件
        std::ifstream file(file_path, std::ios::binary | std::ios::ate);
        if (!file) {
            throw std::runtime_error("Cannot open file: " + file_path);
        }

        // 获取文件大小
        std::streamsize size = file.tellg();
        if (size == -1) {
            throw std::runtime_error("Cann't get file size: " + file_path);
        }
        file.seekg(0, std::ios::beg); // 回到文件开头

        // 分配内存并读取内容
        BYTE_VECTOR buffer(size);
        if (!file.read(reinterpret_cast<char*>(buffer.data()), size)) {
            throw std::runtime_error("Read Failed: " + file_path);
        }

        bytes = std::move(buffer);
        return true;
    }
};

typedef std::string signature_str;




/*
具体签名算法基类：定义了签名算法的基本接口，包括密钥生成、签名和验证方法。
密钥生成: 一般情况下不接收参数，生成公钥和私钥对。
签名生成: 接收消息和私钥，返回签名。
验证签名: 接收消息、签名和公钥，返回验证结果。
*/
template <typename privatekeytype, typename publickeytype, typename publicparameterstype, typename sigtype>
class SignatureAlgorithm {
    virtual void generatepublicparameters(publicparameterstype& publicParameters) = 0;
    virtual void generateKeyPair(privatekeytype& privateKey, publickeytype& publicKey, publicparameterstype& publicParameters) = 0;
    virtual sigtype sign(const PlainMessage& message, const privatekeytype& privateKey, const publicparameterstype& publicParameters) = 0;
    virtual bool verify(const PlainMessage& message, const publickeytype& publicKey, const publicparameterstype& publicParameters, const sigtype& signature) = 0;
};




/*
签名算法管理器：通过该类包装并调用签名算法，包括密钥生成、签名和验证操作。
*/
class SignatureManager_base {
public:
    SignatureManager_base() = default;
    ~SignatureManager_base() = default;

    virtual void init() = 0;
    virtual bool generatepublicparameters() = 0;
    virtual bool generateKeyPair() = 0;
    virtual bool signMessage(const PlainMessage& message, signature_str& signature) = 0;
    virtual bool verifySignature(const PlainMessage& message, const signature_str& signature) = 0;

    virtual std::string get_publicparameters() = 0;
    virtual std::string get_privatekey() = 0;
    virtual std::string get_publickey() = 0;
    virtual bool set_publicparameters(const std::string& str) = 0;
    virtual bool set_privatekey(const std::string& str) = 0;
    virtual bool set_publickey(const std::string& str) = 0;

};



// 检查generateKeyPair存在性
template<typename Algo, typename PrivKey, typename PubKey, typename Params>
struct has_generateKeyPair {
private:
    template<typename T>
    static auto check(T*) -> decltype(
        std::declval<T>().generateKeyPair(
        std::declval<PrivKey&>(),
        std::declval<PubKey&>(),
        std::declval<Params&>()
        ), std::true_type{}
    );

    template<typename>
    static std::false_type check(...);

public:
    static constexpr bool value =
        decltype(check<Algo>(nullptr))::value;
};

// 检查sign方法存在性及返回类型
template<typename Algo, typename PrivKey, typename Params, typename Sig>
struct has_sign_method {
private:
    template<typename T>
    static auto check(T*) -> decltype(
        std::declval<Sig>() = std::declval<T>().sign(
        std::declval<const PlainMessage&>(),
        std::declval<const PrivKey&>(),
        std::declval<const Params&>()
        ), std::true_type{}
    );

    template<typename>
    static std::false_type check(...);

public:
    static constexpr bool value =
        decltype(check<Algo>(nullptr))::value;
};

// 检查verify方法存在性及返回类型
template<typename Algo, typename PubKey, typename Params, typename Sig>
struct has_verify_method {
private:
    template<typename T>
    static auto check(T*) -> decltype(
        std::is_same<decltype(
        std::declval<T>().verify(
        std::declval<const PlainMessage&>(),
        std::declval<const PubKey&>(),
        std::declval<const Params&>(),
        std::declval<const Sig&>()
        )
        ), bool>::value,
        std::true_type{}
    );

    template<typename>
    static std::false_type check(...);

public:
    static constexpr bool value =
        decltype(check<Algo>(nullptr))::value;
};

// 检查签名字符串转换方法
template<typename Sig>
struct has_signature_string_conversion {
private:
    template<typename T>
    static auto check_to_str(T*) -> decltype(
        std::is_same<decltype(std::declval<T>().to_str()), std::string>::value,
        std::true_type{}
    );

    template<typename T>
    static auto check_set_str(T*) -> decltype(
        std::declval<T>().set_by_str(std::declval<const std::string&>()),
        std::true_type{}
    );

    template<typename>
    static std::false_type check_to_str(...);
    template<typename>
    static std::false_type check_set_str(...);

public:
    static constexpr bool has_to_str =
        decltype(check_to_str<Sig>(nullptr))::value;
    static constexpr bool has_set_str =
        decltype(check_set_str<Sig>(nullptr))::value;
    static constexpr bool value = has_to_str && has_set_str;
};


template<typename type_traits>
class SignatureManager : public SignatureManager_base {
public:
    using algotype = typename type_traits::algo;
    using privatekeytype = typename type_traits::private_key;
    using publickeytype = typename type_traits::public_key;
    using publicparameterstype = typename type_traits::params;
    using sigtype = typename type_traits::signature;

    // 编译期检查
    static_assert(
        has_generateKeyPair<algotype,
                           privatekeytype,
                           publickeytype,
                           publicparameterstype>::value,
        "Algorithm type must implement generateKeyPair(PrivKey&, PubKey&, Params&)"
    );

    static_assert(
        has_sign_method<algotype,
                       privatekeytype,
                       publicparameterstype,
                       sigtype>::value,
        "Algorithm type must implement sign(const PlainMessage&, const PrivKey&, const Params&)"
    );

    static_assert(
        has_verify_method<algotype,
                         publickeytype,
                         publicparameterstype,
                         sigtype>::value,
        "Algorithm type must implement verify(...) returning bool"
    );

    static_assert(
        has_signature_string_conversion<publicparameterstype>::value,
        "Signature type must implement to_str() and set_by_str()"
    );

    static_assert(
        has_signature_string_conversion<privatekeytype>::value,
        "Signature type must implement to_str() and set_by_str()"
    );

    static_assert(
        has_signature_string_conversion<publickeytype>::value,
        "Signature type must implement to_str() and set_by_str()"
    );

    static_assert(
        has_signature_string_conversion<sigtype>::value,
        "Signature type must implement to_str() and set_by_str()"
    );



    SignatureManager() = default;
    ~SignatureManager() = default;

    void init() {
        private_key = privatekeytype();
        public_key = publickeytype();
        publicParameters = publicparameterstype();
        signature = sigtype();
    }




    bool generatepublicparameters() {
        try {
            algo.generatepublicparameters(publicParameters);
        }
        catch (const std::exception& e) {
            std::cerr << "[signature_manager][generate publicparameters error]" << e.what() << std::endl;
            return false;
        }
        return true;
    }

    bool generateKeyPair() {
        try {
            algo.generateKeyPair(private_key, public_key, publicParameters);
        }
        catch (const std::exception& e) {
            std::cerr << "[signature_manager][generate key pair error]" << e.what() << std::endl;
            return false;
        }
        return true;
    }

    bool signMessage(const PlainMessage& message, signature_str& signature_str) {
        try {
            signature = algo.sign(message, private_key, publicParameters);
        }
        catch (const std::exception& e) {
            std::cerr << "[signature_manager][sign message error]" << e.what() << std::endl;
            return false;
        }
        signature_str = signature.to_str();
        return true;
    }


    bool verifySignature(const PlainMessage& message, const signature_str& signature_str) {
        try {
            signature.set_by_str(signature_str);
        }
        catch (const std::exception& e) {
            std::cerr << "[signature_manager][set signature error]" << e.what() << std::endl;
            return false;
        }
        try {
            return algo.verify(message, public_key, publicParameters, signature);
        }
        catch (const std::exception& e) {
            std::cerr << "[signature_manager][verification error]" << e.what() << std::endl;
        }
        return false;
    }


    std::string get_publicparameters() override {
        return publicParameters.to_str();
    }

    std::string get_privatekey() override {
        return private_key.to_str();
    }

    std::string get_publickey() override {
        return public_key.to_str();
    }

    bool set_publicparameters(const std::string& str) override {
        try {
            publicParameters.set_by_str(str);
            return true;
        }
        catch (const std::exception& e) {
            std::cerr << "[SignatureManager][set publicparameters error]" << e.what() << std::endl;
            return false;
        }
    }

    bool set_privatekey(const std::string& str) override {
        try {
            private_key.set_by_str(str);
            return true;
        }
        catch (const std::exception& e) {
            std::cerr << "[SignatureManager][set private key error]" << e.what() << std::endl;
            return false;
        }
    }

    bool set_publickey(const std::string& str) override {
        try {
            public_key.set_by_str(str);
            return true;
        }
        catch (const std::exception& e) {
            std::cerr << "[SignatureManager][set public key error]" << e.what() << std::endl;
            return false;
        }
    }



private:
    algotype algo;
    privatekeytype private_key;
    publickeytype public_key;
    publicparameterstype publicParameters;
    sigtype signature;
};












































































#endif /* signature_manager_h */